package cn.xiuxius.embedded.toolwindow.dirvermanager;

import cn.xiuxius.embedded.EasyStcProjectUtils;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.*;
import com.intellij.util.ui.JBFont;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;

import com.intellij.openapi.application.ApplicationManager;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

public class DriveManagerToolWindow extends SimpleToolWindowPanel implements DumbAware {
    private final Project myProject;
    private ComboBox<String> myGroupsComboBox;
    private final Set<String> ALLOWED_EXTENSIONS = new HashSet<>(Arrays.asList("c", "h", "lib", "a51"));
    private Path userDrivePath;
    private final JPanel contentPanel;
    private final Map<File, CategoryPanel> categoryPanels = new HashMap<>();
    private Map<String, String> groupPathMap;

    public DriveManagerToolWindow(@NotNull Project project) {
        super(true, true);
        myProject = project;

        // 使用JPanel替代VerticalBox，并设置BoxLayout
        contentPanel = new JPanel();
        contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
        contentPanel.setBorder(JBUI.Borders.empty(5));

        JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(contentPanel);
        scrollPane.setBorder(JBUI.Borders.empty());

        setLayout(new BorderLayout());
        add(createTopPanel(), BorderLayout.NORTH);
        add(scrollPane, BorderLayout.CENTER);

        loadUserDrivePath();
        refreshContent();
    }

    private JPanel createTopPanel() {
        // 创建工具栏
        DefaultActionGroup actionGroup = new DefaultActionGroup();
        actionGroup.add(new RefreshAction());
        ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("DriveManagerToolbar", actionGroup, true);
        actionToolbar.setTargetComponent(this);

        // 创建组选择下拉框
        myGroupsComboBox = new ComboBox<>();
        updateGroupsComboBox();

        JBLabel groupLabel = new JBLabel("添加到:");
        groupLabel.setFont(Font.getFont(JBFont.DIALOG));

        // 组合工具栏和下拉框
        JPanel topPanel = new JPanel(new BorderLayout());
        topPanel.setBorder(JBUI.Borders.empty(JBUI.scale(5),
                JBUI.scale(5),
                JBUI.scale(5),
                JBUI.scale(5)));

        JPanel comboPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,
                JBUI.scale(5),
                JBUI.scale(0)));
        comboPanel.add(groupLabel);

        myGroupsComboBox.setPreferredSize(new Dimension(
                JBUI.scale(150),
                JBUI.scale(25)
        ));
        comboPanel.add(myGroupsComboBox);

        topPanel.add(actionToolbar.getComponent(), BorderLayout.WEST);
        topPanel.add(comboPanel, BorderLayout.CENTER);

        return topPanel;
    }

    private void loadUserDrivePath() {
        String easyStcHome = System.getenv("EASY_STC_HOME");
        if (easyStcHome != null) {
            userDrivePath = Paths.get(easyStcHome, "user_drive");
        } else {
            showBalloon("未设置 EASY_STC_HOME 环境变量", MessageType.ERROR);
        }
    }

    private void updateGroupsComboBox() {
        // 获取组名和路径映射
        Map<String, String> groupMap = EasyStcProjectUtils.getGroupsWithPaths(myProject);

        // 清空并重新填充下拉框
        myGroupsComboBox.removeAllItems();
        for (String groupName : groupMap.keySet()) {
            myGroupsComboBox.addItem(groupName);
        }
        // 保存组路径映射供后续使用
        this.groupPathMap = groupMap;
    }

    private void refreshContent() {
        contentPanel.removeAll();
        categoryPanels.clear();

        if (userDrivePath != null && Files.exists(userDrivePath) && Files.isDirectory(userDrivePath)) {
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(userDrivePath)) {
                boolean firstExpanded = false;
                for (Path path : stream) {
                    if (Files.isDirectory(path)) {
                        CategoryPanel categoryPanel = new CategoryPanel(path.toFile(), !firstExpanded);
                        // 设置组件的对齐方式
                        categoryPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
                        contentPanel.add(categoryPanel);
                        contentPanel.add(Box.createVerticalStrut(JBUI.scale(5))); // 统一间距
                        categoryPanels.put(path.toFile(), categoryPanel);

                        if (!firstExpanded) {
                            categoryPanel.expand();
                            firstExpanded = true;
                        }
                    }
                }
            } catch (IOException e) {
                showBalloon("读取驱动目录失败: " + e.getMessage(), MessageType.ERROR);
            }
        } else {
            contentPanel.add(createEmptyPanel());
        }

        contentPanel.revalidate();
        contentPanel.repaint();
    }

    private JComponent createEmptyPanel() {
        JPanel emptyPanel = new JPanel(new BorderLayout());
        emptyPanel.setBorder(JBUI.Borders.empty(JBUI.scale(20)));
        emptyPanel.add(new JBLabel("未找到驱动文件", AllIcons.General.Information, SwingConstants.CENTER), BorderLayout.CENTER);
        return emptyPanel;
    }

    private String getFileExtension(String fileName) {
        int lastIndex = fileName.lastIndexOf('.');
        return lastIndex >= 0 ? fileName.substring(lastIndex + 1) : "";
    }

    private void showBalloon(String message, MessageType type) {
        Balloon balloon = JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(
                        message, type, null)
                .setFadeoutTime(3000)
                .createBalloon();

        balloon.show(RelativePoint.getNorthWestOf(this), Balloon.Position.above);
    }

    private class CategoryPanel extends JPanel {
        private final File categoryDir;
        private final JBLabel titleLabel;
        private final JButton expandButton;
        private final JPanel contentPanel;
        private final JScrollPane scrollPane;
        private boolean expanded = false;
        private static final int COLLAPSED_HEIGHT = 40; // 折叠状态高度
        private static final int EXPANDED_CONTENT_HEIGHT = 200; // 展开后内容区域固定高度

        public CategoryPanel(File dir, boolean initiallyCollapsed) {
            super(new BorderLayout());
            this.categoryDir = dir;
            this.expanded = !initiallyCollapsed;

            // 创建标题面板
            JPanel headerPanel = new JPanel(new BorderLayout());
            headerPanel.setBorder(JBUI.Borders.empty(JBUI.scale(5),
                    JBUI.scale(10)));

            titleLabel = new JBLabel(dir.getName(), AllIcons.Nodes.Folder, SwingConstants.LEFT);
            titleLabel.setFont(JBFont.h4().asBold());

            expandButton = new JButton(expanded ? AllIcons.General.ArrowDown : AllIcons.General.ArrowRight);
            expandButton.setBorderPainted(false);
            expandButton.setContentAreaFilled(false);
            expandButton.setFocusPainted(false);
            expandButton.addActionListener(e -> toggleExpand());

            headerPanel.add(titleLabel, BorderLayout.WEST);
            headerPanel.add(expandButton, BorderLayout.EAST);

            // 创建内容面板
            contentPanel = new JPanel();
            contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
            contentPanel.setBorder(JBUI.Borders.empty(JBUI.scale(5),
                    JBUI.scale(10),
                    JBUI.scale(10),
                    JBUI.scale(10)));

            // 使用JBScrollPane支持缩放
            scrollPane = new JBScrollPane(contentPanel);
            scrollPane.setBorder(JBUI.Borders.empty());
            scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

            // 设置边框
            Border lineBorder = JBUI.Borders.customLine(UIUtil.getBoundsColor(), 1);
            setBorder(JBUI.Borders.compound(lineBorder, JBUI.Borders.empty()));
            setBackground(UIUtil.getPanelBackground());

            add(headerPanel, BorderLayout.NORTH);
            add(scrollPane, BorderLayout.CENTER);

            // 初始加载
            if (expanded) {
                loadContent();
                // 设置固定高度（使用JBUI.scale动态计算）
                setExpandedSize();
            } else {
                contentPanel.setVisible(false);
                setPreferredSize(new Dimension(getPreferredSize().width, JBUI.scale(COLLAPSED_HEIGHT)));
                setMaximumSize(new Dimension(Short.MAX_VALUE, JBUI.scale(COLLAPSED_HEIGHT)));
            }

            // 添加鼠标事件
            headerPanel.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent evt) {
                    headerPanel.setBackground(UIUtil.getListSelectionBackground(false));
                }

                @Override
                public void mouseExited(MouseEvent evt) {
                    headerPanel.setBackground(UIUtil.getPanelBackground());
                }

                @Override
                public void mouseClicked(MouseEvent evt) {
                    toggleExpand();
                }
            });
        }

        private void setExpandedSize() {
            // 计算总高度 = 标题高度 + 内容区域固定高度
            int headerHeight = getComponent(0).getPreferredSize().height;
            int totalHeight = headerHeight + JBUI.scale(EXPANDED_CONTENT_HEIGHT);

            setPreferredSize(new Dimension(getPreferredSize().width, totalHeight));
            setMaximumSize(new Dimension(Short.MAX_VALUE, totalHeight));
            setMinimumSize(new Dimension(0, totalHeight));
        }

        public void expand() {
            if (!expanded) {
                toggleExpand();
            }
        }

        private void toggleExpand() {
            expanded = !expanded;
            expandButton.setIcon(expanded ? AllIcons.General.ArrowDown : AllIcons.General.ArrowRight);

            if (expanded) {
                loadContent();
                contentPanel.setVisible(true);
                setExpandedSize();

                // 强制更新布局
                revalidate();
                repaint();

                // 更新父容器布局
                SwingUtilities.invokeLater(() -> {
                    if (getParent() != null) {
                        getParent().revalidate();
                        getParent().repaint();
                    }
                });
            } else {
                contentPanel.removeAll();
                contentPanel.setVisible(false);
                setPreferredSize(new Dimension(getPreferredSize().width, JBUI.scale(COLLAPSED_HEIGHT)));
                setMaximumSize(new Dimension(Short.MAX_VALUE, JBUI.scale(COLLAPSED_HEIGHT)));

                revalidate();
                repaint();
            }
        }

        private void loadContent() {
            contentPanel.removeAll();

            try (DirectoryStream<Path> stream = Files.newDirectoryStream(categoryDir.toPath())) {
                List<File> files = new ArrayList<>();
                List<File> directories = new ArrayList<>();

                for (Path path : stream) {
                    File file = path.toFile();
                    if (Files.isDirectory(file.toPath())) {
                        directories.add(file);
                    } else {
                        String extension = getFileExtension(file.getName()).toLowerCase();
                        if (ALLOWED_EXTENSIONS.contains(extension)) {
                            files.add(file);
                        }
                    }
                }

                // 添加子目录和文件
                for (File dir : directories) {
                    CategoryPanel subCategory = new CategoryPanel(dir, true);
                    subCategory.setAlignmentX(Component.LEFT_ALIGNMENT);
                    contentPanel.add(subCategory);
                    contentPanel.add(Box.createVerticalStrut(JBUI.scale(5)));
                }

                for (File file : files) {
                    contentPanel.add(new FileRowPanel(file));
                    contentPanel.add(Box.createVerticalStrut(JBUI.scale(3)));
                }
            } catch (IOException e) {
                contentPanel.add(new JBLabel("加载内容失败: " + e.getMessage(), AllIcons.General.Error, SwingConstants.LEFT));
            }

            // 确保内容面板更新布局
            contentPanel.revalidate();
            contentPanel.repaint();
        }
    }

    private class FileRowPanel extends JPanel {
        private final File driveFile;
        private final JBTextField fileNameField;
        private final JButton addButton;

        public FileRowPanel(File driveFile) {
            super(new BorderLayout(JBUI.scale(10), JBUI.scale(0)));
            this.driveFile = driveFile;

            // 文件图标
            JBLabel fileIconLabel = new JBLabel();
            fileIconLabel.setIcon(AllIcons.FileTypes.Any_type);

            // 文件名输入框（使用JBUI.scale动态计算尺寸）
            fileNameField = new JBTextField(driveFile.getName());
            fileNameField.setBorder(JBUI.Borders.empty(JBUI.scale(2), JBUI.scale(5)));
            fileNameField.setPreferredSize(new Dimension(
                    JBUI.scale(200),
                    JBUI.scale(25)
            ));
            fileNameField.setMaximumSize(new Dimension(
                    Short.MAX_VALUE,
                    JBUI.scale(25)
            ));

            // 添加按钮（使用JBUI.scale动态计算尺寸）
            addButton = new JButton("添加");
            addButton.setIcon(AllIcons.Actions.AddFile);
            addButton.setPreferredSize(new Dimension(
                    JBUI.scale(100),
                    JBUI.scale(25)
            ));
            addButton.setMaximumSize(new Dimension(
                    JBUI.scale(100),
                    JBUI.scale(25)
            ));
            addButton.addActionListener(e -> addWithRename(driveFile, fileNameField.getText()));

            // 设置样式（使用JBUI.scale设置行高）
            setBorder(JBUI.Borders.compound(
                    JBUI.Borders.customLine(UIUtil.getInactiveTextColor(), 0, 0, 1, 0),
                    JBUI.Borders.empty(JBUI.scale(2), JBUI.scale(10))
            ));
            setBackground(UIUtil.getListBackground());
            setPreferredSize(new Dimension(0, JBUI.scale(40)));

            add(fileIconLabel, BorderLayout.WEST);
            add(fileNameField, BorderLayout.CENTER);

            JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT,
                    JBUI.scale(5),
                    JBUI.scale(0)));
            buttonPanel.add(addButton);
            add(buttonPanel, BorderLayout.EAST);
        }
    }

    private void addWithRename(File driveFile, String newFileName) {
        String selectedGroup = (String) myGroupsComboBox.getSelectedItem();
        if (selectedGroup == null || selectedGroup.isEmpty()) {
            showBalloon("请选择目标组", MessageType.WARNING);
            return;
        }

        // 检查groupPathMap是否已初始化且包含选中的组
        if (groupPathMap == null || !groupPathMap.containsKey(selectedGroup)) {
            showBalloon("目标组配置不存在", MessageType.ERROR);
            return;
        }

        // 获取配置文件中定义的组路径
        String groupPath = groupPathMap.get(selectedGroup);
        if (groupPath == null || groupPath.trim().isEmpty()) {
            showBalloon("目标组路径配置为空", MessageType.ERROR);
            return;
        }

        // 检查文件名合法性
        if (newFileName == null || newFileName.trim().isEmpty()) {
            showBalloon("文件名不能为空", MessageType.WARNING);
            return;
        }

        // 检查文件扩展名是否允许
        String extension = getFileExtension(newFileName).toLowerCase();
        if (!ALLOWED_EXTENSIONS.contains(extension)) {
            showBalloon("不支持的文件类型: " + extension, MessageType.WARNING);
            return;
        }

        ApplicationManager.getApplication().runWriteAction(() -> {
            try {
                VirtualFile baseDir = myProject.getBaseDir();
                if (baseDir == null) {
                    showBalloon("项目目录不存在", MessageType.ERROR);
                    return;
                }

                // 构建目标路径：项目根目录 + 组配置路径 + 新文件名
                Path targetPath = Paths.get(baseDir.getPath(), groupPath, newFileName);

                // 确保目标目录存在（自动处理相对路径和rootPath）
                Path targetDir = targetPath.getParent();
                if (!Files.exists(targetDir)) {
                    Files.createDirectories(targetDir);
                }

                // 检查目标文件是否已存在
                if (Files.exists(targetPath)) {
                    int result = JOptionPane.showConfirmDialog(
                            this,
                            "文件 " + newFileName + " 已存在，是否覆盖?",
                            "确认覆盖",
                            JOptionPane.YES_NO_OPTION
                    );
                    if (result != JOptionPane.YES_OPTION) {
                        return;
                    }
                }

                // 复制文件并使用新文件名
                Files.copy(driveFile.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING);

                showBalloon("文件已添加并重命名为: " + newFileName, MessageType.INFO);

                // 刷新项目目录
                baseDir.refresh(false, true);
            } catch (IOException e) {
                showBalloon("添加文件失败: " + e.getMessage(), MessageType.ERROR);
            }
        });
    }

    private class RefreshAction extends AnAction {
        public RefreshAction() {
            super("刷新", "刷新驱动文件列表", AllIcons.Actions.Refresh);
        }

        @Override
        public void actionPerformed(@NotNull AnActionEvent e) {
            updateGroupsComboBox();
            refreshContent();
        }
    }
}